package com.zzl.study.nacos;

import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingMaintainService;
import com.alibaba.nacos.api.naming.NamingService;
import com.zzl.study.nacos.properties.NacosMultiDiscoveryProperties;
import com.zzl.study.nacos.properties.NacosServerConfiguration;
import jakarta.annotation.PostConstruct;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

import static com.alibaba.nacos.api.NacosFactory.createMaintainService;
import static com.alibaba.nacos.api.NacosFactory.createNamingService;

/**
 * Nacos多注册中心服务管理器
 *
 * @author: zhangzl
 * @date: 2025/7/14 22:26
 * @version: 1.0
 */
public class NacosServiceMultiManager {

    /**
     * Nacos多注册中心配置
     */
    private NacosMultiDiscoveryProperties nacosMultiDiscoveryProperties;

    /**
     * Nacos注册中心服务缓存Map
     */
    private final ConcurrentHashMap<String, NamingService> namingServiceMap = new ConcurrentHashMap<>();

    /**
     * Nacos服务维护服务缓存Map
     */
    private final ConcurrentHashMap<String, NamingMaintainService> namingMaintainServiceMap = new ConcurrentHashMap<>();

    /**
     * 初始化
     */
    public void init() {
        this.namingServiceMap.clear();
        this.namingMaintainServiceMap.clear();
        Map<String, NacosServerConfiguration> multiple = this.nacosMultiDiscoveryProperties.getMultiple();
        multiple.keySet().forEach(registryName -> {
            Properties nacosProperties = this.nacosMultiDiscoveryProperties.getNacosProperties(registryName);
            NamingService namingService = createNewNamingService(nacosProperties);
            this.namingServiceMap.putIfAbsent(registryName, namingService);
            NamingMaintainService namingMaintainService = createNamingMaintainService(nacosProperties);
            this.namingMaintainServiceMap.putIfAbsent(registryName, namingMaintainService);
        });
    }

    /**
     * 获取Nacos注册中心服务
     *
     * @param registryName 注册中心名称
     * @return Nacos注册中心服务
     */
    public NamingService getNamingService(String registryName) {
        return this.namingServiceMap.get(registryName);
    }

    /**
     * 获取所有Nacos注册中心服务
     *
     * @return 所有Nacos注册中心服务
     */
    public List<NamingService> getNamingServices() {
        return new ArrayList<>(this.namingServiceMap.values());
    }

    /**
     * 获取Nacos服务维护服务
     *
     * @param registryName 注册中心名称
     * @return Nacos服务维护服务
     */
    public NamingMaintainService getNamingMaintainService(String registryName) {
        return this.namingMaintainServiceMap.get(registryName);
    }

    /**
     * 获取所有Nacos服务维护服务
     *
     * @return 所有Nacos服务维护服务
     */
    public List<NamingMaintainService> getNamingMaintainServices() {
        return new ArrayList<>(this.namingMaintainServiceMap.values());
    }

    /**
     * 判断Nacos注册中心配置是否改变
     *
     * @param currentNacosMultiDiscoveryProperties Nacos多注册中心配置
     * @return 是否改变
     */
    public boolean isNacosDiscoveryInfoChanged(NacosMultiDiscoveryProperties currentNacosMultiDiscoveryProperties) {
        return !Objects.isNull(this.nacosMultiDiscoveryProperties) && !this.nacosMultiDiscoveryProperties.equals(currentNacosMultiDiscoveryProperties);
    }

    /**
     * 设置Nacos多注册中心配置
     *
     * @param nacosMultiDiscoveryProperties Nacos多注册中心配置
     */
    public void setNacosMultiDiscoveryProperties(NacosMultiDiscoveryProperties nacosMultiDiscoveryProperties) {
        this.nacosMultiDiscoveryProperties = nacosMultiDiscoveryProperties;
        init();
    }

    /**
     * Nacos服务关闭
     *
     * @throws NacosException Nacos异常
     */
    public void nacosServiceShutDownAll() throws NacosException {
        if (!CollectionUtils.isEmpty(this.namingServiceMap)) {
            Iterator<Map.Entry<String, NamingService>> iterator = this.namingServiceMap.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<String, NamingService> entry = iterator.next();
                NamingService namingService = entry.getValue();
                namingService.shutDown();
                iterator.remove();
            }
        }
        if (!CollectionUtils.isEmpty(this.namingMaintainServiceMap)) {
            Iterator<Map.Entry<String, NamingMaintainService>> iterator = this.namingMaintainServiceMap.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<String, NamingMaintainService> entry = iterator.next();
                NamingMaintainService namingMaintainService = entry.getValue();
                namingMaintainService.shutDown();
                iterator.remove();
            }
        }
    }

    /**
     * 创建新的Nacos注册中心服务
     *
     * @param properties Nacos配置
     * @return Nacos注册中心服务
     */
    private NamingService createNewNamingService(Properties properties) {
        try {
            return createNamingService(properties);
        } catch (NacosException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 创建新的Nacos服务维护服务
     *
     * @param properties Nacos配置
     * @return Nacos服务维护服务
     */
    private NamingMaintainService createNamingMaintainService(Properties properties) {
        try {
            return createMaintainService(properties);
        } catch (NacosException e) {
            throw new RuntimeException(e);
        }
    }

}
